/* wrap.h
Copyright (c) 2008 Michael Zahniser
Please note the license terms (MIT license) at the end of this document.

Header file for the templated wrap() function, which returns the next place to
break a line of text in order to wrap it to a given width.
*/

#ifndef __MZ_WRAP_H__
#define __MZ_WRAP_H__



// This is the base class for functors representing ways of measuring the width
// of a text string.
template <class Text>
class TextMeasure {
public:
	virtual ~TextMeasure() {}
	virtual int operator()(typename Text::const_iterator first, typename Text::const_iterator last) const = 0;
};



// This TextMeasure just counts the number of characters.
// Appropriate for wrapping text for a fixed-width display, such as the console.
template <class Text>
class CountChars : public TextMeasure<Text> {
public:
	virtual int operator()(typename Text::const_iterator first, typename Text::const_iterator last) const;
};



// Starting at the given position, find the next point at which to break the 
// text in order to kep the width less than the given amount.
template <class It, class Text>
It wrap(It it, It stopIt, const TextMeasure<Text> &measure, int width);



// CountChars::operator():
template <class Text>
int CountChars<Text>::operator()(typename Text::const_iterator first, typename Text::const_iterator last) const
{
	return static_cast<int>(last - first);
}



// wrap:
// Starting at the given position, find the next point at which to break the 
// text in order to keep the width less than the given amount.
// Note: because stopIt, even if it is the end of the file, may be a valid wrap
// position (e.g. if the file ends in '\n'), a line that need not be wrapped
// is reported by returning stopIt + 1.
template <class It, class Text>
It wrap(It it, It stopIt, const TextMeasure<Text> &measure, int width)
{
	It startIt = it;
	It best = startIt;
	
	// Search forward.
	while(it < stopIt)
	{
		It old = it;
		++it;
		
		if(*old == '\n')
			return it;
		else if(*old <= ' ')
			best = it;
		else if(measure(startIt, it) > width)
		{
			if(best == startIt)
				return old;
			return best;
		}
	}
	
	return stopIt + 1;
}



#endif



/* Copyright (c) 2008 Michael Zahniser

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. */

